import java.awt.Point;
import java.util.Collection;
import java.util.Iterator;
import java.util.TreeMap;

public class ClientMap {
	private TreeMap mapTree;
	private ClientEntity[][] mapArray;
	public final int X_MAX = 100;
	public final int Y_MAX = 100;
	private ClientEntity toReturn;
	public ClientMap()
	{
		mapTree = new TreeMap();
		mapArray = new ClientEntity[X_MAX][Y_MAX];
	}
	public boolean isValid(Point loc)
	{
		if(loc==null || loc.x >X_MAX-1 || loc.y >Y_MAX-1 || loc.x<0 || loc.y<0)
			return false;
		return true;
	}
	public boolean isValid(int x, int y)
	{
		if(x >X_MAX-1 || y >Y_MAX-1 || x<0 || y<0)
			return false;
		return true;
	}
	public boolean isValid(ClientEntity o)
	{
		if(o==null || o.data==null || o.data.location==null)
			return false;
		return true;
	}
	public boolean add(ClientEntity o)
	{
		if(!isValid(o)|| !isEmpty(o.data.location) || get(o.data.id)!=null)
			return false;
		mapTree.put(new Integer(o.data.id), o);
		mapArray[o.data.location.x][o.data.location.y]= o;
		return true;
	}
	public ClientEntity get(Point loc)
	{
		if(isValid(loc))
			return mapArray[loc.x][loc.y];
		return null;
	}
	public ClientEntity get(int x, int y)
	{
		if(isValid(x,y))
			return mapArray[x][y];
		return null;
	}
	public ClientEntity get(int id){return (ClientEntity)mapTree.get(new Integer(id));}
	public void remove(ClientEntity o)
	{
		if(isValid(o) && isValid(o.data.location))
		{
			mapArray[o.data.location.x][o.data.location.y] = null;
			mapTree.remove(new Integer(o.data.id));
		}
	}
	
	public ClientEntity remove(Point o)
	{
		if(isValid(o))
		{
			toReturn = mapArray[o.x][o.y];
			if(isValid(toReturn))
			{
				mapArray[o.x][o.y]=null;
				return (ClientEntity)mapTree.remove(new Integer(toReturn.data.id));
			}
		}
		return null;
	}
	public ClientEntity remove(int x, int y)
	{
		if(isValid(x,y))
		{
			toReturn = mapArray[x][y];
			if(isValid(toReturn))
			{
				mapArray[x][y]=null;
				return (ClientEntity)mapTree.remove(new Integer(toReturn.data.id));
			}
		}
		return null;
	}
	public ClientEntity remove(int id)
	{
		toReturn = (ClientEntity)mapTree.remove(new Integer(id));
		if(isValid(toReturn) && isValid(toReturn.data.location))
		{
			mapArray[toReturn.data.location.x][toReturn.data.location.y]=null;
			return toReturn;
		}
		return null;
	}

	public boolean isEmpty(int x, int y)
	{
		if(isValid(x,y))
			return mapArray[x][y]==null;
		return false;
	}
	public boolean isEmpty(Point p)
	{
		if(isValid(p))
			return mapArray[p.x][p.y]==null;
		return false;
	}
	
	public int size(){return mapTree.size();}
	
	public boolean move(ClientEntity o, Point moveTo)
	{
		if(isValid(o) && isValid(o.data.location) && isValid(moveTo) && isEmpty(moveTo) && !isEmpty(o.data.location))
		{
			mapArray[o.data.location.x][o.data.location.y]=null;
			mapArray[moveTo.x][moveTo.y]=o;
			o.data.location=moveTo;
			return true;
		}
		return false;
	}
	
	
	
	public Iterator idSetIterator(){return new ClientSetIterator(mapTree.keySet(), mapArray, mapTree);}
	public Iterator ClientEntitySetIterator(){return new ClientSetIterator(mapTree.values(), mapArray, mapTree);}
	
	public String toString()
	{
		String s = new String();
		Iterator iter = mapTree.entrySet().iterator();
		while(iter.hasNext())
		{
			toReturn = (ClientEntity)iter.next();
			if(isValid(toReturn) && isValid(toReturn.data.location))
				s=s.concat("("+toReturn.data.location.x+","+toReturn.data.location.y+"):"+toReturn.data.id+"\t");
		}
		return s;
	}
}
class ClientSetIterator implements Iterator
{
	private Collection c;
	private Iterator myIter;
	private Object lastReturned=null;
	private ClientEntity[][] mapArray;
	private TreeMap mapTree;
	private ClientEntity temp;
	public ClientSetIterator(Collection c, ClientEntity[][] array, TreeMap myMap)
	{
		this.c = c;
		myIter = c.iterator();
		mapArray = array;
		mapTree = myMap;
	}
	public boolean hasNext()
	{
		return myIter.hasNext();
	}
	public Object next()
	{
		lastReturned = myIter.next();
		return lastReturned;
	}
	public void remove()
	{
		temp=null;
		if(lastReturned instanceof Integer)//an id
			temp = (ClientEntity)mapTree.get(lastReturned);
		myIter.remove();//this will handle death by not calling next or whatever
		if(lastReturned!=null)
		{
			if(lastReturned instanceof Integer)//an id
			{
				if(temp!=null)//assume everthing else is just fine, point existance, bounds etc if not the Map shoulda died anyway
					mapArray[temp.data.location.x][temp.data.location.y]=null;
			}
			else//an ClientEntity
				mapArray[((ClientEntity)lastReturned).data.location.x][((ClientEntity)lastReturned).data.location.y]=null;
		}
	}
}
